﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.ServiceLocation;
using Pap.Data;
using Pap.Data.Abstraction.Utils;
using Pap.Services.WorkflowEngine;
using Utils;

namespace Pap.Services
{
    /// <summary>
    /// 
    /// </summary>
    public class LoanExecutionService : ILoanExecutionService
    {
        /// <summary>
        /// 
        /// </summary>
        IDatabase _Database;
        /// <summary>
        /// 
        /// </summary>
        IWorkflowService _WorkFlow;

        /// <summary>
        /// Initializes a new instance of the <see cref="LoanExecutionService"/> class.
        /// </summary>
        /// <param name="Database">The database.</param>
        /// <param name="workFlow">The work flow.</param>
        public LoanExecutionService(IDatabase Database, IWorkflowService workFlow)
        {
            _Database = Database;
            _WorkFlow = workFlow;
        }

        #region Loan Execution
        /// <summary>
        /// Validates the gurantor warning.
        /// true if the payed limit is more than .75, false if less
        /// </summary>
        /// <param name="ssn">The SSN.</param>
        /// <returns>
        /// true if the payed limit is more than .75, false if less
        /// </returns>
        public bool ValidateGurantorWarning(string ssn)
        {
            var endedLoans = _WorkFlow.GetInStep(Steps.EndedLoans).Union(_WorkFlow.GetInStep(Steps.RefusedLoans)).Union(
                _WorkFlow.GetInStep(Steps.RefusedExecutionList));

            var guarntedLoansExecutions = _Database.LoanExecutions.Where(loanEx => !endedLoans.Contains(loanEx.LoanID) && loanEx.GuarantorSSN.Equals(ssn));

            foreach (var loanEx in guarntedLoansExecutions)
            {
                var totalRequired = loanEx.LoanExecutionInstallmentsLst.Sum(install => install.TotalInstallmentAmount + install.PenaltyAmount);
                var totalPaid = loanEx.LoanExecutionInstallmentsLst.Sum(install => install.LoanInstallmentPaymentLst.Sum(payment => payment.PaymentAmount));

                if (totalPaid / totalRequired < 0.75)
                    return false;
            }
            return true;
        }

        /// <summary>
        /// Validates the gurantor.
        /// </summary>
        /// <param name="ssn">The SSN.</param>
        /// <returns></returns>
        public bool ValidateGurantor(string ssn)
        {
            var endedLoans = _WorkFlow.GetInStep(Steps.EndedLoans).Union(_WorkFlow.GetInStep(Steps.RefusedLoans)).Union(
               _WorkFlow.GetInStep(Steps.RefusedExecutionList));

# warning this code crashes if it you select single() because the system doesn't prevent redundant customer SSID
            //var guarantor = _Database.Customers.SingleOrDefault(cus => cus.SSN.Equals(ssn));
            var guarantor = _Database.Customers.FirstOrDefault(cus => cus.SSN.Equals(ssn));
            if (guarantor != null)
            {
                //check to see this gurantor has no other guranteed loans
                if (_Database.CustomerLoans.Where(loan => loan.GuarantorID == guarantor.CustomerID).Count() > 0)
                    return false;

                if (_Database.CustomerLoans.Where(loan => loan.CustomerID == guarantor.CustomerID && !endedLoans.Contains(loan.LoanID)).Count() > 0)
                    return false;
            }

            return true;

        }
        /// <summary>
        /// Creates the loan execution.
        /// </summary>
        /// <param name="loan">The loan.</param>
        /// <param name="boardLoan">The board loan.</param>
        /// <param name="executionDate">The execution date.</param>
        /// <param name="checkNumber">The check number.</param>
        /// <param name="checkDate">The check date.</param>
        /// <param name="guarantorName">Name of the guarantor.</param>
        /// <param name="guarantorSSN">The guarantor SSN.</param>
        /// <param name="note">The note.</param>
        /// <param name="createInstallments">if set to <c>true</c> [create installments].</param>
        /// <returns></returns>
        public ILoanExecution CreateLoanExecution(ICustomerLoan loan, IBoardLoan boardLoan, DateTime executionDate, string checkNumber, DateTime checkDate, string guarantorName, string guarantorSSN, string note, bool createInstallments)
        {
#warning Shift execution date to tomorrow if it passes the limit
            //if (ValidateGurantor(guarantorSSN))
            //{
            ILoanExecution loanExecution = ServiceLocator.Current.GetInstance<ILoanExecution>();
            loanExecution.LoanExecutionID = Guid.NewGuid();
            loanExecution.LoanID = loan.LoanID;
            loanExecution.CheckNumber = checkNumber;
            loanExecution.CheckDate = checkDate;
            loanExecution.ExecutionDate = executionDate;
            loanExecution.GuarantorName = guarantorName;
            loanExecution.GuarantorSSN = guarantorSSN;

            loanExecution.LoanAmount = boardLoan.BoardLoanAmount.Value;
            loanExecution.LoanExecutionStatus = true;
            loanExecution.LoanPaymentMethodID = boardLoan.BoardpaymentMethodID.Value;
            loanExecution.LoanPeriod = boardLoan.BoardPaymentPeriod.Value;


            loanExecution.InterestPercentage = loan.ProjectStage.ProjectObj.ProfitPercent;

            double interestTotalAmount = loanExecution.LoanAmount * loanExecution.LoanPeriod * (double)loanExecution.InterestPercentage / (12 * 100);

            loanExecution.TotalLoanAmount = loanExecution.LoanAmount + interestTotalAmount;
            if (createInstallments)
            {
                IEnumerable<ILoanExecutionInstallment> installments = CreateLoanExecutionInstallments(loanExecution);
                foreach (var item in installments)
                {
                    loanExecution.AddInstallment(item);
                }
            }
            return loanExecution;
            //}
            //else
            //{
            //    return null;
            //}
        }

        /// <summary>
        /// Updates the loan execution.
        /// </summary>
        /// <param name="loanExecution">The loan execution.</param>
        /// <param name="loan">The loan.</param>
        /// <param name="boardLoan">The board loan.</param>
        /// <param name="executionDate">The execution date.</param>
        /// <param name="checkNumber">The check number.</param>
        /// <param name="checkDate">The check date.</param>
        /// <param name="guarantorName">Name of the guarantor.</param>
        /// <param name="guarantorSSN">The guarantor SSN.</param>
        /// <param name="note">The note.</param>
        /// <returns></returns>
        public bool UpdateLoanExecution(ILoanExecution loanExecution, ICustomerLoan loan, IBoardLoan boardLoan, DateTime executionDate, string checkNumber, DateTime checkDate, string guarantorName, string guarantorSSN, string note)
        {
#warning Shift execution date to tomorrow if it passes the limit
            if (ValidateGurantor(guarantorSSN))
            {
                loanExecution.LoanID = loan.LoanID;
                loanExecution.ExecutionDate = executionDate;
                loanExecution.CheckNumber = checkNumber;
                loanExecution.CheckDate = checkDate;
                loanExecution.GuarantorName = guarantorName;
                loanExecution.GuarantorSSN = guarantorSSN;

                loanExecution.LoanAmount = boardLoan.BoardLoanAmount.Value;
                loanExecution.LoanExecutionStatus = true;
                loanExecution.LoanPaymentMethodID = boardLoan.BoardpaymentMethodID.Value;
                loanExecution.LoanPeriod = boardLoan.BoardPaymentPeriod.Value;


                loanExecution.InterestPercentage = loan.ProjectStage.ProjectObj.ProfitPercent;

                double interestTotalAmount = loanExecution.LoanAmount * loanExecution.LoanPeriod * (double)loanExecution.InterestPercentage / (12 * 100);

                loanExecution.TotalLoanAmount = loanExecution.LoanAmount + interestTotalAmount;
                IEnumerable<ILoanExecutionInstallment> installments = CreateLoanExecutionInstallments(loanExecution);
                foreach (var item in installments)
                {
                    loanExecution.AddInstallment(item);
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Creates the loan execution.
        /// </summary>
        /// <param name="lastExecution">The last execution.</param>
        /// <param name="executionDate">The execution date.</param>
        /// <param name="paymentPeriod">The payment period.</param>
        /// <param name="loanAmount">The loan amount.</param>
        /// <returns></returns>
        public ILoanExecution CreateLoanExecution(ILoanExecution lastExecution, DateTime executionDate, int paymentPeriod, double loanAmount)
        {
#warning Shift execution date to tomorrow if it passes the limit
            if (ValidateGurantor(lastExecution.GuarantorSSN))
            {
                ILoanExecution loanExecution = ServiceLocator.Current.GetInstance<ILoanExecution>();
                loanExecution.LoanExecutionID = Guid.NewGuid();
                loanExecution.LoanID = lastExecution.LoanID;
                loanExecution.CheckNumber = lastExecution.CheckNumber;
                loanExecution.CheckDate = lastExecution.CheckDate;
                loanExecution.ExecutionDate = executionDate;
                loanExecution.GuarantorName = lastExecution.GuarantorName;
                loanExecution.GuarantorSSN = lastExecution.GuarantorSSN;

                loanExecution.LoanAmount = loanAmount;
                loanExecution.LoanExecutionStatus = true;
                loanExecution.LoanPaymentMethodID = lastExecution.LoanPaymentMethodID;
                loanExecution.LoanPeriod = paymentPeriod;


                loanExecution.InterestPercentage = lastExecution.InterestPercentage;

                double interestTotalAmount = loanExecution.LoanAmount * loanExecution.LoanPeriod * (double)loanExecution.InterestPercentage / (12 * 100);

                loanExecution.TotalLoanAmount = loanExecution.LoanAmount + interestTotalAmount;
                IEnumerable<ILoanExecutionInstallment> installments = CreateLoanExecutionInstallments(loanExecution);
                foreach (var item in installments)
                {
                    loanExecution.AddInstallment(item);
                }
                return loanExecution;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Creates the loan execution installments.
        /// </summary>
        /// <param name="loanExecution">The loan execution.</param>
        /// <returns></returns>
        public IEnumerable<ILoanExecutionInstallment> CreateLoanExecutionInstallments(ILoanExecution loanExecution)
        {
            List<ILoanExecutionInstallment> lst = new List<ILoanExecutionInstallment>();

            double interestTotalAmount = loanExecution.LoanAmount * loanExecution.LoanPeriod * (double)loanExecution.InterestPercentage / (12 * 100);
            double loanTotalAmount = loanExecution.TotalLoanAmount;

            if (loanExecution.LoanPaymentMethodID == Enums.ToString(PaymentMethods.Periodical).ToGuid())
            {
                double installmentTotalAmount = Math.Ceiling(loanTotalAmount / loanExecution.LoanPeriod);
                double installmentOriginalAmount = Math.Ceiling(loanExecution.LoanAmount / loanExecution.LoanPeriod);

                double installmentInterest = installmentTotalAmount - installmentOriginalAmount;
                ILoanExecutionInstallment installment = null;

                int i = 0;
                for (i = 0; i < loanExecution.LoanPeriod - 1; i++)
                {
                    installment = ServiceLocator.Current.GetInstance<ILoanExecutionInstallment>();
                    installment.LoanExecutionInstallmentID = Guid.NewGuid();
                    installment.LoanExecutionID = loanExecution.LoanExecutionID;

                    installment.InstallmentDate = loanExecution.ExecutionDate.AddMonths(i + 1);

                    //total
                    installment.TotalInstallmentAmount = installmentTotalAmount;
                    //original
                    installment.OriginalInstallmentAmount = installmentOriginalAmount;
                    //interest
                    installment.InterestInstallmentAmount = installmentInterest;

                    installment.IsPaid = false;
                    lst.Add(installment);
                }

                installment = ServiceLocator.Current.GetInstance<ILoanExecutionInstallment>();
                installment.LoanExecutionInstallmentID = Guid.NewGuid();
                installment.LoanExecutionID = loanExecution.LoanExecutionID;

                installment.InstallmentDate = loanExecution.ExecutionDate.AddMonths(i + 1);

                //total
                installment.TotalInstallmentAmount = loanTotalAmount - ((loanExecution.LoanPeriod - 1) * installmentTotalAmount);
                //original
                installment.OriginalInstallmentAmount = loanExecution.LoanAmount - ((loanExecution.LoanPeriod - 1) * installmentOriginalAmount);
                //interest
                installment.InterestInstallmentAmount = interestTotalAmount - ((loanExecution.LoanPeriod - 1) * installmentInterest);

                installment.IsPaid = false;
                lst.Add(installment);
            }
            else
            {
                double installmentTotalAmount = Math.Ceiling(interestTotalAmount / loanExecution.LoanPeriod);
                double installmentOriginalAmount = 0;

                ILoanExecutionInstallment installment = null;

                int i = 0;
                for (i = 0; i < loanExecution.LoanPeriod - 1; i++)
                {
                    installment = ServiceLocator.Current.GetInstance<ILoanExecutionInstallment>();
                    installment.LoanExecutionInstallmentID = Guid.NewGuid();
                    installment.LoanExecutionID = loanExecution.LoanExecutionID;

                    installment.InstallmentDate = loanExecution.ExecutionDate.AddMonths(i + 1);

                    //total
                    installment.TotalInstallmentAmount = installmentTotalAmount;
                    //original
                    installment.OriginalInstallmentAmount = installmentOriginalAmount;
                    //interest
                    installment.InterestInstallmentAmount = installmentTotalAmount;

                    installment.IsPaid = false;
                    lst.Add(installment);
                }

                installment = ServiceLocator.Current.GetInstance<ILoanExecutionInstallment>();
                installment.LoanExecutionInstallmentID = Guid.NewGuid();
                installment.LoanExecutionID = loanExecution.LoanExecutionID;

                installment.InstallmentDate = loanExecution.ExecutionDate.AddMonths(i + 1);

                //total
                installment.TotalInstallmentAmount = loanExecution.LoanAmount + (interestTotalAmount - ((loanExecution.LoanPeriod - 1) * installmentTotalAmount));
                //original
                installment.OriginalInstallmentAmount = loanExecution.LoanAmount;
                //interest
                installment.InterestInstallmentAmount = installment.TotalInstallmentAmount - loanExecution.LoanAmount;

                installment.IsPaid = false;
                lst.Add(installment);
                return lst;
            }
            return lst;
        }


        #endregion

        #region LoanPayments


        /// <summary>
        /// Calculates the penalities.
        /// </summary>
        public void CalculatePenalities()
        {
            var LoansExcutions = _Database.CustomerLoans.Select(loan => loan.LoanExecutionLst);

            //var LoansExcutions = _Database.CustomerLoans.Select(loan => loan.LoanExecutionLst.Where(loanExcute => loanExcute.LoanExecutionStatus).OrderBy(loanEx => loanEx.ExecutionDate).LastOrDefault());
            foreach (var loanExecutionlst in LoansExcutions)
            {
                var loanEx = loanExecutionlst.Where(loanExcute => loanExcute.LoanExecutionStatus).OrderBy(loanexe => loanexe.ExecutionDate).Last();
                var loanExInstallments = loanEx.LoanExecutionInstallmentsLst.Where(loanExInst => !loanExInst.IsPaid && loanExInst.InstallmentDate.Date < DateTime.Today.Date);
                foreach (var loanExInstall in loanExInstallments)
                {

                    loanExInstall.PenaltyDays = (loanExInstall.InstallmentDate.Date - DateTime.Today.Date).Days;
                    if (loanEx.LoanPaymentMethodID.Equals(Enums.ToString(PaymentMethods.Periodical)))
                    {
                        loanExInstall.PenaltyAmount = (loanExInstall.TotalInstallmentAmount * loanExInstall.PenaltyDays) / 100;
                    }



                    //else
                    //    if (loanEx.LoanPaymentMethodID.Equals(Enums.ToString(PaymentMethods.GracePeriod)))
                    //    {

                    //    }
                }
            }
        }


        /// <summary>
        /// Gets all excuation dues.
        /// </summary>
        /// <param name="exceutionID">The exceution ID.</param>
        /// <returns></returns>
        public double GetAllExcuationDues(Guid exceutionID)
        {
            double totalDues = 0;
            ILoanExecution loanExecution = _Database.LoanExecutions.Single(loanExec => loanExec.LoanExecutionID == exceutionID);
            foreach (var loanExecutionInstallment in loanExecution.LoanExecutionInstallmentsLst.Where(loanExInstall => !loanExInstall.IsPaid && loanExInstall.InstallmentDate.Date <= DateTime.Today))
            {
                totalDues += (loanExecutionInstallment.TotalInstallmentAmount + loanExecutionInstallment.PenaltyAmount);
                totalDues -= GetInstallmentPaymentAmount(loanExecutionInstallment.LoanExecutionInstallmentID);
            }
            return totalDues;
        }

        /// <summary>
        /// Gets all excuation amount.
        /// </summary>
        /// <param name="exceutionID">The exceution ID.</param>
        /// <returns></returns>
        public double GetAllExcuationAmount(Guid exceutionID)
        {
            double totalAmount = 0;
            ILoanExecution loanExecution = _Database.LoanExecutions.Single(loanExec => loanExec.LoanExecutionID == exceutionID);
            foreach (var loanExecutionInstallment in loanExecution.LoanExecutionInstallmentsLst.Where(loanExInstall => !loanExInstall.IsPaid))
            {
                totalAmount += (loanExecutionInstallment.TotalInstallmentAmount + loanExecutionInstallment.PenaltyAmount);
                totalAmount -= GetInstallmentPaymentAmount(loanExecutionInstallment.LoanExecutionInstallmentID);
            }
            return totalAmount;
        }

        /// <summary>
        /// Gets the installment payment amount.
        /// </summary>
        /// <param name="loanInstallmentID">The loan installment ID.</param>
        /// <returns></returns>
        public double GetInstallmentPaymentAmount(Guid loanInstallmentID)
        {
            double totalPayment = 0;
            var installment = _Database.LoanExecutionInstallments.Single(loanexInstallment => loanexInstallment.LoanExecutionInstallmentID == loanInstallmentID);

            foreach (var payment in installment.LoanInstallmentPaymentLst)
            {
                totalPayment += payment.PaymentAmount;
            }

            return totalPayment;
        }

        /// <summary>
        /// Pays for execution.
        /// </summary>
        /// <param name="executionID">The execution ID.</param>
        /// <param name="paymentAmount">The payment amount.</param>
        /// <param name="ReceipteNumber">The receipte number.</param>
        /// <param name="paymentDate">The payment date.</param>
        /// <returns>
        /// returns true if all execution's installments are paied
        /// </returns>
        public bool PayForExecution(Guid executionID, double paymentAmount, long ReceipteNumber, DateTime paymentDate)
        {
            ILoanExecution loanExcution = this._Database.LoanExecutions.Single(loanexec => loanexec.LoanExecutionID == executionID);
            IReceipt receiptObj = ServiceLocator.Current.GetInstance<IReceipt>();
            receiptObj.ReceiptID = Guid.NewGuid();
            receiptObj.ReceiptTypeID = Enums.ToString(ReceiptTypes.InstallmentReceipt).ToGuid();
            receiptObj.ReceiptNumber = ReceipteNumber;
            receiptObj.ReceiptDate = DateTime.Now;
            receiptObj.ReceiptAmount = paymentAmount;
            _Database.Insert<IReceipt>(receiptObj);

            //var orderdInstallments = loanExcution.LoanExecutionInstallmentsLst.Where(installment => !installment.IsPaid && installment.InstallmentDate.Date <= DateTime.Today.Date).OrderBy(inst => inst.InstallmentDate);
            var orderdInstallments = loanExcution.LoanExecutionInstallmentsLst.Where(inst => !inst.IsPaid).OrderBy(inst => inst.InstallmentDate);
            foreach (var executionInstallment in orderdInstallments)
            {
                double installmentPaymentAmount = GetInstallmentPaymentAmount(executionInstallment.LoanExecutionInstallmentID);
                if ((paymentAmount + installmentPaymentAmount) >= (executionInstallment.TotalInstallmentAmount + executionInstallment.PenaltyAmount))
                {
                    double newPayment = executionInstallment.TotalInstallmentAmount + executionInstallment.PenaltyAmount - installmentPaymentAmount;
                    paymentAmount -= newPayment;
                    executionInstallment.IsPaid = true;
                    ILoanInstallmentPayment newPaymentObj = ServiceLocator.Current.GetInstance<ILoanInstallmentPayment>();
                    newPaymentObj.LoanInstallmentPaymentID = Guid.NewGuid();
                    newPaymentObj.LoanExecutionInstallmentID = executionInstallment.LoanExecutionInstallmentID;
                    newPaymentObj.PaymentAmount = newPayment;
                    newPaymentObj.PaymentDate = paymentDate;
                    newPaymentObj.ReceiptID = receiptObj.ReceiptID;
                    _Database.Insert<ILoanInstallmentPayment>(newPaymentObj);
                }
                else
                {
                    if (paymentAmount > 0)
                    {
                        ILoanInstallmentPayment newPaymentObj = ServiceLocator.Current.GetInstance<ILoanInstallmentPayment>();
                        newPaymentObj.LoanInstallmentPaymentID = Guid.NewGuid();
                        newPaymentObj.LoanExecutionInstallmentID = executionInstallment.LoanExecutionInstallmentID;
                        newPaymentObj.PaymentAmount = paymentAmount;
                        newPaymentObj.PaymentDate = paymentDate;
                        newPaymentObj.ReceiptID = receiptObj.ReceiptID;
                        _Database.Insert<ILoanInstallmentPayment>(newPaymentObj);
                    }
                    break;
                }
            }
            if (orderdInstallments.Count() == 0)
            {
                loanExcution.LoanExecutionStatus = false;
                return true;
            }
            return false;
        }

        public IReceipt PayInstallment(Guid installmentId, double paymentAmount, long receiptNumber, DateTime paymentDate)
        {
            var installment =
                _Database.LoanExecutionInstallments.Single(x => x.LoanExecutionInstallmentID == installmentId);

            IReceipt receiptObj = ServiceLocator.Current.GetInstance<IReceipt>();
            receiptObj.ReceiptID = Guid.NewGuid();
            receiptObj.ReceiptTypeID = Enums.ToString(ReceiptTypes.InstallmentReceipt).ToGuid();
            receiptObj.ReceiptNumber = receiptNumber;
            receiptObj.ReceiptDate = DateTime.Now;
            receiptObj.ReceiptAmount = paymentAmount;
            _Database.Insert<IReceipt>(receiptObj);

            ILoanInstallmentPayment newPaymentObj = ServiceLocator.Current.GetInstance<ILoanInstallmentPayment>();
            newPaymentObj.LoanInstallmentPaymentID = Guid.NewGuid();
            newPaymentObj.LoanExecutionInstallmentID = installment.LoanExecutionInstallmentID;
            newPaymentObj.PaymentAmount = paymentAmount;
            newPaymentObj.PaymentDate = paymentDate;
            newPaymentObj.ReceiptID = receiptObj.ReceiptID;
            _Database.Insert<ILoanInstallmentPayment>(newPaymentObj);

            var totalPaid = installment.LoanInstallmentPaymentLst.Sum(x => x.PaymentAmount) + paymentAmount;
            var duePaid = installment.TotalInstallmentAmount + installment.PenaltyAmount;
            installment.IsPaid = duePaid == totalPaid;

            return receiptObj;
        }

        #endregion

        /// <summary>
        /// Gets the loan history.
        /// </summary>
        /// <param name="lastLoanExecution">The last loan execution.</param>
        /// <param name="closeType">Type of the close.</param>
        /// <param name="notes">The notes.</param>
        /// <returns></returns>
        public ICustomerLoanHistory GetLoanHistory(ILoanExecution lastLoanExecution, LoanHistoryCloseTypes closeType, string notes)
        {
            ICustomerLoanHistory loanHistory = ServiceLocator.Current.GetInstance<ICustomerLoanHistory>();
            loanHistory.LoanHistoryID = Guid.NewGuid();
            loanHistory.LoanID = lastLoanExecution.LoanID;
            loanHistory.CustomerName = lastLoanExecution.CustomerLoan.CustomerObj.CustomerName;
            loanHistory.LoanCloseDate = DateTime.Now;
            loanHistory.LoanExecutionDate = lastLoanExecution.ExecutionDate;
            loanHistory.LoanHistoryCloseTypeID = Enums.ToString(closeType).ToGuid();
            loanHistory.LoanProjectStageID = lastLoanExecution.CustomerLoan.ProjectStageID;
            loanHistory.Notes = notes;

            loanHistory.LastDiscreteDelay = lastLoanExecution.LoanExecutionInstallmentsLst.Select(inst => inst.PenaltyDays).Sum();
            loanHistory.LastConsecutiveDelay = lastLoanExecution.LoanExecutionInstallmentsLst.Select(inst => inst.PenaltyDays).Max();

            return loanHistory;
        }
    }
}
